using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.ComponentModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

namespace ContentPipelineExtension
{
    /// <summary>
    /// This class will be instantiated by the XNA Framework Content Pipeline
    /// to apply custom processing to content data, converting an object of
    /// type TInput to TOutput. The input and output types may be the same if
    /// the processor wishes to alter data without changing its type.
    ///
    /// This should be part of a Content Pipeline Extension Library project.
    ///
    /// TODO: change the ContentProcessor attribute to specify the correct
    /// display name for this processor.
    /// </summary>
    [ContentProcessor(DisplayName = "ContentPipelineExtension.CustomMaterialProcessor")]
    public class CustomMaterialProcessor : MaterialProcessor
    {
        /// <summary>
        /// Converts a material.
        /// </summary>
        public override MaterialContent Process(MaterialContent p_input,
                                                ContentProcessorContext p_context)
        {
            // Create a new effect material.
            EffectMaterialContent customMaterial = new EffectMaterialContent();

            // Point the new material at our custom effect file.
            string effectFile = Path.GetFullPath("Effects\\MaterialShader30.fx");

            customMaterial.Effect = new ExternalReference<EffectContent>(effectFile);

            foreach (KeyValuePair<String,ExternalReference<TextureContent>> texture in p_input.Textures)
            {
                if (texture.Key == "Texture")
                {
                    customMaterial.Textures.Add("diffuseTexture", texture.Value);
                }
                if (texture.Key == CustomModelProcessor.normalMapKey)
                {
                    customMaterial.Textures.Add("normalTexture", texture.Value);
                }
                if (texture.Key == CustomModelProcessor.specularMapKey)
                {
                    customMaterial.Textures.Add("specularTexture", texture.Value);
                }
            }

            // Chain to the base material processor.
            return base.Process(customMaterial, p_context);
        }

        /// <summary>
        /// Builds a texture for use by this material.
        /// </summary>
        protected override ExternalReference<TextureContent> BuildTexture(  // remove if no texture needs special processing
                                            string textureName,
                                            ExternalReference<TextureContent> texture,
                                            ContentProcessorContext context)
        {
            if (textureName == "normalTexture")
            {
                // put the normal map through the special NormalMapTextureProcessor,
                // which will convert it to a signed format.
                return context.BuildAsset<TextureContent, TextureContent>(texture, "NormalMapTextureProcessor");
            }
            if (textureName == "diffuseTexture" || textureName == "specularTexture")
            {
                return context.BuildAsset<TextureContent, TextureContent>(texture, "DiffSpecTextureProcessor");
            }

            // Apply default processing to all other textures.
            return base.BuildTexture(textureName, texture, context);
        }
    }
}